package com.hzbank.qwencode.controller;

import com.hzbank.qwencode.model.QwencodeRequest;
import com.hzbank.qwencode.model.QwencodeResponse;
import com.hzbank.qwencode.model.QwencodeStreamChunk;
import com.hzbank.qwencode.service.QwencodeService;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import com.hzbank.qwencode.config.QwencodeConfig;

/**
 * QwenCode 控制器类
 * 提供RESTful API接口
 */
@RestController
@RequestMapping("/")
@Tag(name = "QwenCode API", description = "提供qwencode命令行工具的RESTful API接口")
@Slf4j
public class QwencodeController {

    private final QwencodeService qwencodeService;
    private final ObjectMapper objectMapper;
    private final QwencodeConfig config;

    @Autowired
    public QwencodeController(QwencodeService qwencodeService, ObjectMapper objectMapper, 
                             QwencodeConfig config) {
        this.qwencodeService = qwencodeService;
        this.objectMapper = objectMapper;
        this.config = config;
    }

    /**
     * 健康检查端点
     */
    @GetMapping("/health")
    @Operation(summary = "健康检查", description = "检查服务是否正常运行")
    @ApiResponse(responseCode = "200", description = "服务健康状态")
    public ResponseEntity<Map<String, Object>> healthCheck() {
        Map<String, Object> response = new HashMap<>();
        response.put("status", "healthy");
        response.put("service", "qwencode-api");
        response.put("timestamp", Instant.now().toEpochMilli());
        return ResponseEntity.ok(response);
    }

    /**
     * 服务信息端点
     */
    @GetMapping("/info")
    @Operation(summary = "服务信息", description = "获取服务的基本信息")
    @ApiResponse(responseCode = "200", description = "服务信息")
    public ResponseEntity<Map<String, Object>> getServiceInfo() {
        Map<String, Object> response = new HashMap<>();
        response.put("name", "QwenCode API");
        response.put("description", "提供qwencode命令行工具的RESTful API接口");
        response.put("version", "1.0.0");
        response.put("java_version", System.getProperty("java.version"));
        response.put("os", System.getProperty("os.name"));
        
        Map<String, String> endpoints = new HashMap<>();
        endpoints.put("health", "/health");
        endpoints.put("info", "/info");
        endpoints.put("encode", "/encode");
        endpoints.put("encode_stream", "/encode/stream");
        
        response.put("endpoints", endpoints);
        return ResponseEntity.ok(response);
    }

    /**
     * 编码文本端点（非流式）
     */
    @PostMapping("/encode")
    @Operation(summary = "文本编码", description = "对文本进行编码处理")
    @ApiResponse(responseCode = "200", description = "编码成功", 
                content = @Content(schema = @Schema(implementation = QwencodeResponse.class)))
    @ApiResponse(responseCode = "500", description = "编码失败")
    public ResponseEntity<QwencodeResponse> encodeText(
            @Parameter(description = "编码请求参数", required = true)
            @RequestBody QwencodeRequest request) {
        try {
            log.info("🔄 收到编码请求: 文本长度={}, 参数={}", request.getText().length(), request.getEncodingParams());
            
            // 调用服务进行编码
            String encodedText = qwencodeService.encodeText(
                    request.getText(),
                    request.getEncodingParams(),
                    request.getWorkingDirectory()
            );
            
            // 构建响应
            QwencodeResponse response = new QwencodeResponse(
                    encodedText,
                    request.getText(),
                    request.getEncodingParams()
            );
            
            log.info("✅ 编码请求处理成功");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            String errorMsg = "编码失败: " + e.getMessage();
            log.error("❌ 编码请求处理失败: {}", errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }
    }

    /**
     * 流式编码文本端点
     */
    @PostMapping(value = "/encode/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Operation(summary = "流式文本编码", description = "流式对文本进行编码并返回结果")
    @ApiResponse(responseCode = "200", description = "流式编码结果")
    @ApiResponse(responseCode = "500", description = "编码失败")
    public org.springframework.web.servlet.mvc.method.annotation.SseEmitter encodeTextStream(
            @Parameter(description = "编码请求参数", required = true)
            @RequestBody QwencodeRequest request) {
        
        // 创建SseEmitter，设置超时时间
        org.springframework.web.servlet.mvc.method.annotation.SseEmitter emitter = 
                new org.springframework.web.servlet.mvc.method.annotation.SseEmitter(
                        (long) config.getCommandExecutionTimeout() * 1000);
        
        // 在单独的线程中处理编码请求
        new Thread(() -> {
            try {
                if (request.isStream()) {
                    // 流式处理
                    log.info("🌊 接收到流式编码请求: {}...", 
                             request.getText().length() > 50 ? 
                             request.getText().substring(0, 50) + "..." : request.getText());
                    
                    qwencodeService.encodeTextStream(
                            request.getText(),
                            request.getEncodingParams(),
                            request.getWorkingDirectory(),
                            chunk -> {
                                try {
                                    QwencodeStreamChunk streamChunk = new QwencodeStreamChunk(chunk, false);
                                    String json = objectMapper.writeValueAsString(streamChunk);
                                    emitter.send(json + "\n");
                                } catch (Exception e) {
                                    log.error("❌ 发送流式数据失败: {}", e.getMessage());
                                }
                            }
                    );
                    
                    // 发送结束标记
                    QwencodeStreamChunk endChunk = new QwencodeStreamChunk("", true);
                    String json = objectMapper.writeValueAsString(endChunk);
                    emitter.send(json + "\n");
                    emitter.complete();
                    
                    log.info("✅ 流式编码请求处理成功");
                } else {
                    // 非流式处理
                    log.info("ℹ️  虽然在流式端点，但根据stream参数使用非流式处理");
                    
                    String encodedText = qwencodeService.encodeText(
                            request.getText(),
                            request.getEncodingParams(),
                            request.getWorkingDirectory()
                    );
                    
                    QwencodeStreamChunk chunk = new QwencodeStreamChunk(encodedText, true);
                    String json = objectMapper.writeValueAsString(chunk);
                    emitter.send(json + "\n");
                    emitter.complete();
                    
                    log.info("✅ 非流式编码请求处理成功");
                }
            } catch (Exception e) {
                String errorMsg = "流式编码失败: " + e.getMessage();
                log.error("❌ 流式编码请求处理失败: {}", errorMsg, e);
                try {
                    Map<String, String> errorResponse = new HashMap<>();
                    errorResponse.put("error", errorMsg);
                    String json = objectMapper.writeValueAsString(errorResponse);
                    emitter.send(json + "\n");
                } catch (Exception ex) {
                    log.error("❌ 发送错误信息失败", ex);
                }
                emitter.completeWithError(e);
            }
        }).start();
        
        return emitter;
    }
}